package com.c.opt.tool;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.util.*;
import cn.hutool.db.Entity;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.StaticLog;
import ntd.util.config.common.enums.EnumDataType;
import ntd.util.frame.auth.ToolLogin;
import ntd.util.frame.data.bo.MetaTableField;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.List;
import java.util.Map;

public class ToolEntity {

    /**
     * entity 转 对象
     * @param entity
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T toBean(Entity entity, Class<T> clazz) {
        if (ObjectUtil.isNull(entity) || ObjectUtil.isNull(clazz)) {
            return null;
        }
        T t = null;
        try {
            t = entity.toBeanWithCamelCase(clazz.newInstance());
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        for (Map.Entry<String, Object> entry : entity.entrySet()) {
            Object value = entry.getValue();
            if (ObjectUtil.isNotNull(value) && EnumUtil.isEnum(value)) {
                Method getValue = ClassUtil.getDeclaredMethod(value.getClass(), "getValue");
                if (ObjectUtil.isNotNull(getValue)) {
                    try {
                        BeanUtil.setFieldValue(t, StrUtil.toCamelCase(entry.getKey()), getValue.invoke(value));
                    } catch (IllegalAccessException e) {
                        throw new RuntimeException(e);
                    } catch (InvocationTargetException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }
        return t;
    }

    public static <T> Entity toEntity(T t) {
        return toEntity(t, true);
    }

    /**
     * bean 转 entity
     * @param t
     * @param <T>
     * @return
     */
    public static <T> Entity toEntity(T t, boolean isToUnderlineCase) {
        Entity entity = Entity.parse(t, isToUnderlineCase, true);
        for (Map.Entry<String, Object> entry : entity.entrySet()) {
            Object value = entry.getValue();
            if (ObjectUtil.isNotNull(value) && EnumUtil.isEnum(value)) {
                Method getValue = ClassUtil.getDeclaredMethod(value.getClass(), "getValue");
                if (ObjectUtil.isNotNull(getValue)) {
                    try {
                        entity.set(entry.getKey(), getValue.invoke(value));
                    } catch (IllegalAccessException | InvocationTargetException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }
        return entity;
    }


    /**
     * json 转 entity
     * @param syncData
     * @param isNew
     * @param metaTableFields
     * @return
     */
    public static Entity toEntity(Map<String, Object> syncData, List<MetaTableField> metaTableFields, Boolean isNew) {
        Entity entity = new Entity();

        if (ObjectUtil.isNull(isNew)) {
            isNew = ObjectUtil.isEmpty(syncData.get("id"));
        }

        boolean finalIsNew = isNew;

        metaTableFields.forEach(metaTableField -> {
            String name = metaTableField.getName();
            Object val = ObjectUtil.defaultIfNull(syncData.get(name), syncData.get(StrUtil.toCamelCase(name)));
            String valStr = Convert.toStr(val);
            if (StrUtil.isBlankIfStr(val)) {
                if (metaTableField.getName().equals("id") && !EnumDataType.NUMBER.equals(metaTableField.getEnumDataType()) && finalIsNew) {
                    val = generatorDateId();
                }
                if (metaTableField.getName().equals("created_by") && finalIsNew) {
                    val = ToolLogin.getCurrUserId();
                }
                if (metaTableField.getName().equals("created_date") && finalIsNew) {
                    val = new Date();
                }
                if (metaTableField.getName().equals("tenant_id") && finalIsNew) {
                    val = ToolLogin.getCurrTenantId();
                }
            }
            if (metaTableField.getName().equals("updated_by")) {
                val = ToolLogin.getCurrUserId();
            }
            if (metaTableField.getName().equals("updated_date")) {
                val = new Date();
            }
            if (EnumDataType.DATE.equals(metaTableField.getEnumDataType())) {
                val = Convert.toDate(val);
            }
            if (JSONUtil.isTypeJSON(valStr)) {
                val = valStr;
            }
            if (ObjectUtil.isNotNull(val)) {
                entity.set(name, val);
            }
        });
        // id特殊处理
        Opt.ofBlankAble(entity.getStr("id")).ifPresent(id -> entity.set("id", id));
        return entity;
    }

    private static String generatorDateId() {
        return DateUtil.format(DateUtil.date(), "yyyyMMddHHmmssSSS") + RandomUtil.randomString(15);
    }
}
